package ar.edu.unq.wannaplay.utils;

import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.Interval;

import ar.edu.unq.wannaplay.calendareable.Calendareable;

public class Calendar {
    private CalendarMatrix matrix;

    private Interval monthInterval;

    private int month;

    private int year;

    private int firstDay;

    public Calendar(final int month, final int year) {
        this.month = month;
        this.year = year;

        final DateTime monthInit = new DateTime(year, month, 1, 0, 0, 0, 0);

        int nextYear = year;
        int nextMonth;
        if (month < 12) {
            nextMonth = month + 1;
        } else {
            nextMonth = 1;
            nextYear++;
        }
        final DateTime monthFinish = new DateTime(nextYear, nextMonth, 1, 0, 0, 0, 0).minusDays(1);

        monthInterval = new Interval(monthInit, monthFinish);
        firstDay = monthInit.getDayOfWeek();

        this.createMatrix();
    }

    private void createMatrix() {
        int cantDays = monthInterval.getEnd().getDayOfMonth();

        int rows = this.calculateRows(cantDays);
        int cols = 7;
        DayInfo infoType = new DayInfo();
        matrix = new CalendarMatrix(rows, cols, infoType);

        int day = 1;
        int col = firstDay - 1;
        int row = 0;
        while (day <= cantDays) {
            matrix.putDay(row, col, day);
            if (col == 6) {
                col = 0;
                row++;
            } else {
                col++;
            }
            day++;
        }
    }

    private int calculateRows(final int cantDays) {
        int rows = 1;

        int daysCant = cantDays;
        daysCant -= 8 - firstDay;

        rows += daysCant / 7;
        int rest = daysCant % 7;

        if (rest > 0) {
            rows++;
        }

        return rows;
    }

    public void fill(final List<Calendareable> info) {

        for (Calendareable elem : info) {
            if (monthInterval.contains(elem.getInterval().getStart())) {
                Pair<Integer, Integer> sCoorPair = matrix.getDayCoordinates(elem.getInterval().getStart()
                        .getDayOfMonth());
                matrix.addElem(sCoorPair.getFirst(), sCoorPair.getSecond(), elem, CalendareableState.START);
            }

            if (monthInterval.contains(elem.getInterval().getEnd())) {
                Pair<Integer, Integer> fCoorPair = matrix
                        .getDayCoordinates(elem.getInterval().getEnd().getDayOfMonth());
                matrix.addElem(fCoorPair.getFirst(), fCoorPair.getSecond(), elem, CalendareableState.FINISH);
            }
        }
    }

    public DayInfo getDayInfo(final int day) {
        Pair<Integer, Integer> coorPair = matrix.getDayCoordinates(day);
        return (DayInfo) matrix.getInfo(coorPair.getFirst(), coorPair.getSecond());
    }

    public CalendarMatrix getMatrix() {
        return matrix;
    }

    public void setMatrix(final CalendarMatrix matrix) {
        this.matrix = matrix;
    }

    public Interval getMonthInterval() {
        return monthInterval;
    }

    public void setMonthInterval(final Interval monthInterval) {
        this.monthInterval = monthInterval;
    }

    public int getFirstDay() {
        return firstDay;
    }

    public void setFirstDay(final int firstDay) {
        this.firstDay = firstDay;
    }

    @Override
    public String toString() {
        return " LU - MA - MI - JU - VI - SA - DO " + matrix.toString();
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(final int month) {
        this.month = month;
    }

    public int getYear() {
        return year;
    }

    public void setYear(final int year) {
        this.year = year;
    }
}
